package com.rambo.xpd.reflect.demo;

import com.rambo.xpd.reflect.vo.BaseStudentVO;
import com.rambo.xpd.reflect.vo.PrimaryScholar;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Create by Rambo on 2017/7/10
 **/
public class ReflectDemo {

    private static Object setBaseAtrByReflect(Map<String, Object> baseParam, Class clazz) throws Exception {
        Object instance = clazz.newInstance();
        Class superclass = clazz.getSuperclass();
        Method[] declaredMethods = superclass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            if (declaredMethod.getName().contains("set")) {
                if (declaredMethod.getName().contains("Stu_id")) {
                    declaredMethod.invoke(instance, baseParam.get("stu_id"));
                    continue;
                }

                if (declaredMethod.getName().contains("Stu_name")) {
                    declaredMethod.invoke(instance, baseParam.get("stu_name"));
                    continue;
                }
                if (declaredMethod.getName().contains("Stu_age")) {
                    declaredMethod.invoke(instance, (Integer) baseParam.get("stu_age"));
                    continue;
                }
                if (declaredMethod.getName().contains("Stu_birthday")) {
                    declaredMethod.invoke(instance, (Date) baseParam.get("stu_birthday"));
                }
            }
        }
        return instance;
    }

    private static Object setBaseAtrByIntrospect(Map<String, Object> baseParam, Class clazz) throws Exception {
        Object instance = clazz.newInstance();
        Class superclass = clazz.getSuperclass();
        PropertyDescriptor propDesc;
        Method methodSetUserName;
        for (Field field : superclass.getDeclaredFields()) {
            propDesc = new PropertyDescriptor(field.getName(), clazz);
            methodSetUserName = propDesc.getWriteMethod();
            methodSetUserName.invoke(instance, baseParam.get(field.getName()));
        }
        return instance;
    }

    private static Object setBaseAtrByBeanUtil(Map<String, Object> baseParam, Class clazz) throws Exception {
        Object instance = clazz.newInstance();
        BeanUtils.setProperty(instance, "stu_id", baseParam.get("stu_id"));
        BeanUtils.setProperty(instance, "stu_name", baseParam.get("stu_name"));
        BeanUtils.setProperty(instance, "stu_age", baseParam.get("stu_age"));
        BeanUtils.setProperty(instance, "stu_birthday", baseParam.get("stu_birthday"));
        return instance;
    }

    private static <T extends BaseStudentVO> T setBaseAtrByGenenic(Map<String, Object> baseParam, T t) {
        t.setStu_id(baseParam.get("stu_id").toString());
        t.setStu_name(baseParam.get("stu_name").toString());
        t.setStu_age((Integer) baseParam.get("stu_age"));
        t.setStu_birthday((Date) baseParam.get("stu_birthday"));
        return t;
    }

    public static void main(String[] args) throws Exception {
        Map<String, Object> map = new HashMap<>();
        map.put("stu_id", "001");
        map.put("stu_name", "rambo");
        map.put("stu_age", 14);
        map.put("stu_birthday", new Date());

        PrimaryScholar primaryScholar = (PrimaryScholar) setBaseAtrByReflect(map, PrimaryScholar.class);
        System.out.println("setBaseAtrByReflect:" + ToStringBuilder.reflectionToString(primaryScholar));

        PrimaryScholar primaryScholar1 = (PrimaryScholar) setBaseAtrByIntrospect(map, PrimaryScholar.class);
        System.out.println("setBaseAtrByIntrospect：" + ToStringBuilder.reflectionToString(primaryScholar1));

        PrimaryScholar primaryScholar2 = (PrimaryScholar) setBaseAtrByBeanUtil(map, PrimaryScholar.class);
        System.out.println("setBaseAtrByBeanUtil:" + ToStringBuilder.reflectionToString(primaryScholar2));


        PrimaryScholar primaryScholar3 = setBaseAtrByGenenic(map, new PrimaryScholar());
        System.out.println("setBaseAtrByGenenic：" + ToStringBuilder.reflectionToString(primaryScholar3));
    }
}